package com.shanzmoo.core.domain.pay;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.shanzmoo.base.constant.e.WxTradeTypeEnum;
import com.shanzmoo.db.trade.entity.PayOrderEntity;
import lombok.*;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 支付订单
 * </p>
 *
 * @author Gzhao
 * @since 2020-12-09
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class WxPayOrderDto implements Serializable {
    private static final long serialVersionUID = 1758L;

    /**
     * 支付单号:(微信交易单号out_trade_no)
     */
    private String outTradeNo;

    /**
     * (微信)商品描述
     */
    private String body;

    /**
     * (微信)标价币种
     */
    private String feeType;

    /**
     * (微信)标价金额，单位：分
     */
    private String totalFee;

    /**
     * (微信)ip
     */
    private String spbillCreateIp;

    /**
     * (微信)交易类型
     */
    private String tradeType;

    /**
     * (微信)trade_type=NATIVE时，此参数必传
     */
    private String productId;

    /**
     * 付款码
     */
    private String authCode;

    /**
     * 用户标识
     */
    private String openid;

    /**
     * 场景信息，用于上报H5支付支付的场景信息
     */
    private String sceneInfo;


    public static WxPayOrderDto createBySceneInfo(PayOrderEntity order, String sceneInfo) {
        return create(order, null, null, sceneInfo);
    }

    public static WxPayOrderDto createByAuthCode(PayOrderEntity order, String authCode) {
        return create(order, authCode, null, null);
    }

    public static WxPayOrderDto createByOpenid(PayOrderEntity order, String openid) {
        return create(order, null, openid, null);
    }

    public static WxPayOrderDto create(PayOrderEntity order) {
        return create(order, null, null, null);
    }


    public static WxPayOrderDto create(PayOrderEntity order, String authCode, String openid, String sceneInfo) {
        return WxPayOrderDto.builder()
                .outTradeNo(order.getPayNo())
                .body(order.getBody())
                .feeType(order.getFeeType())
                .totalFee(String.valueOf(order.getTotalFee()))
                .spbillCreateIp(order.getIp())
                .tradeType(order.getTradeType())
                .productId(order.getProductId())
                .authCode(authCode)
                .openid(openid)
                .sceneInfo(sceneInfo)
                .build();
    }
    public Map<String, String> convertMap() {
        return convertMap(null);
    }

    public Map<String, String> convertMap(String notifyUrl) {
        Map<String, String> data = new HashMap<>();
        data.put("body", this.body);
        data.put("out_trade_no", this.outTradeNo);
        data.put("total_fee", this.totalFee);
        data.put("spbill_create_ip", this.spbillCreateIp);

        if (WxTradeTypeEnum.NATIVE.getDesc().equals(this.tradeType)) {
            data.put("trade_type", this.tradeType);
            if (StrUtil.isNotBlank(notifyUrl)){
                data.put("notify_url", notifyUrl);
            }
            // 商品ID, trade_type=NATIVE时, 参数必传
            data.put("product_id", this.productId);

        } else if (WxTradeTypeEnum.MICROPAY.getDesc().equals(this.tradeType)) {
            data.put("auth_code", this.authCode);

        } else if (WxTradeTypeEnum.JSAPI.getDesc().equals(this.tradeType)) {
            data.put("trade_type", this.tradeType);
            data.put("openid", this.openid);
            data.put("notify_url", notifyUrl);

        } else if (WxTradeTypeEnum.MWEB.getDesc().equals(this.tradeType)) {
            data.put("trade_type", this.tradeType);
            data.put("notify_url", notifyUrl);
            data.put("scene_info", this.sceneInfo);
        }

        // 交易结束时间 (订单一个小时以内有效)
        data.put("time_expire", getTimeExpire());

        return data;
    }

    /**
     *
     *  获取交易结束时间 ，示例 2018-06-08T10:34:56+08:00
     * @author Gzhao 2021/1/16
     * @return
     */
    private String getTimeExpire() {
        LocalDateTime time = LocalDateTimeUtil.offset(LocalDateTime.now(), 1, ChronoUnit.HOURS);

        return LocalDateTimeUtil.format(time, "yyyyMMddHHmmss");
    }
}
